﻿using Kimd.Vision;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace Kimd.Motion
{
    public class Coordinate2D
    {
        private ControlCard _card;
        private short _crdNo;
        private bool _inMove;
        public Axis Axis1 { get; set; }
        public Axis Axis2 { get; set; }
        public string Description { get; set; }
        public string Module { get; set; }
        public bool NoCheckLimit { get; set; }
        [XmlIgnore]
        public bool StopMovement { get; set; } = false;
        public Coordinate2D()
        {
            
        }
        public Coordinate2D(ControlCard card, short crdNo, Axis axis1, Axis axis2, string description, string module)
            : this()
        {
            this._card = card;
            this._crdNo = crdNo;
            this.Axis1 = axis1;
            this.Axis2 = axis2;
            this.Description = description;
            this.Module = module;
        }
        public bool MoveLine(double[] destination, out string stopReason, int workMode, bool wait = true)
        {
            stopReason = "";
            ClearErr();
            if (!Axis1.Ready || !Axis2.Ready)
            {
                stopReason = $"坐标系:{Description}未达运动条件";
                return false;
            }
            if (!_inMove)
                _inMove = true;
            else
            {
                stopReason = $"轴:{Description}已在运动中";
                return false;
            }
            if (Math.Abs(destination[0] - Axis1.Position) < 0.005 &&
                Math.Abs(destination[1] - Axis2.Position) < 0.005)
            {
                _inMove = false;
                return true;
            }
            if (Axis1.Vel == 0 || Axis1.Acc == 0 || Axis1.Dec == 0)
            {
                stopReason = $"{Description}未设置移动速度";
                _inMove = false;
                return false;
            }
            bool direction1 = destination[0] - Axis1.Position >= 0;
            bool direction2 = destination[1] - Axis2.Position >= 0; 
            if (!Axis1.MoveConditionCheck(direction1, out stopReason))
            {
                _inMove = false;
                return false;
            }
            if (!Axis2.MoveConditionCheck(direction2, out stopReason))
            {
                _inMove = false;
                return false;
            }
            _card.CoordinateOperator.MoveLine2(_card.CardNo,
                                               this._crdNo,
                                               Axis1.GetAxisNo(),
                                               Axis2.GetAxisNo(),
                                               new int[2]{ Axis1.MM2Pulse(destination[0]),
                                                           Axis2.MM2Pulse(destination[1]) },
                                               new AxisSpeed()
                                               {
                                                   VelStart = Axis1.VelStart,
                                                   Vel = Axis1.Vel,
                                                   VelEnd = Axis1.VelEnd,
                                                   Acc = Axis1.Acc,
                                                   Dec = Axis1.Dec,
                                                   STime = Axis1.STime,
                                               });

            if (!wait)
            {
                _inMove = false;
                return true;
            }

            while (!IsMovementDone() && !StopMovement)
            {
                if (!Axis1.MoveConditionCheck(direction1, out stopReason))
                {
                    _inMove = false;
                    return false;
                }
                if (!Axis2.MoveConditionCheck(direction2, out stopReason))
                {
                    _inMove = false;
                    return false;
                }
                //TimeSpan ts = DateTime.Now - now;
                //if (ts.Seconds * 1000 + ts.Milliseconds > movetime * 1000 + 1000)
                //{
                //    //MachineMessage.CallException(ExceptionType.FatalErr, "Axis", string.Format("轴{0}移动中超时!", Description));
                //    this.Stop(false);
                //    _inMove = false;
                //    return false;
                //}
                Thread.Sleep(2);
            }

            if (!Axis1.MoveConditionCheck(direction1, out stopReason))
            {
                _inMove = false;
                return false;
            }
            if (!Axis2.MoveConditionCheck(direction2, out stopReason))
            {
                _inMove = false;
                return false;
            }
            //自动模式下记录lastposition
            if (workMode == 1)
            {
                Axis1.LastPosition = destination[0];
                Axis2.LastPosition = destination[1];
            }
            return true;
        }
        public bool WaitCrdInPosition(double[] destination, int workMode, out string stopReason)
        {
            bool direction1 = destination[0] - Axis1.Position >= 0;
            bool direction2 = destination[1] - Axis2.Position >= 0;
            DateTime now = DateTime.Now;
            StopMovement = false;
            while (!IsMovementDone() && !StopMovement)
            {
                if (!Axis1.MoveConditionCheck(direction1, out stopReason))
                {
                    _inMove = false;
                    return false;
                }
                if (!Axis2.MoveConditionCheck(direction2, out stopReason))
                {
                    _inMove = false;
                    return false;
                }
                //TimeSpan ts = DateTime.Now - now;
                //if (ts.Seconds * 1000 + ts.Milliseconds > movetime * 1000 + 1000)
                //{
                //    //MachineMessage.CallException(ExceptionType.FatalErr, "Axis", string.Format("轴{0}移动中超时!", Description));
                //    this.Stop(false);
                //    _inMove = false;
                //    return false;
                //}
                Thread.Sleep(2);
            }

            if (!Axis1.MoveConditionCheck(direction1, out stopReason))
            {
                _inMove = false;
                return false;
            }

            if (!Axis2.MoveConditionCheck(direction2, out stopReason))
            {
                _inMove = false;
                return false;
            }

            //StopType stopType = _card.AxisOperator.GetStopReason(_card.CardNo, _axisNo);
            //if (stopType != StopType.Normal && stopType != StopType.Other && stopType != StopType.Cmd)
            //{
            //    _inMove = false;
            //    stopReason = $"轴:{Description}异常停止,原因:{EnumHelper.GetEnumDescriptionFromValue(stopType)}";
            //    return false;
            //}
            if (!Axis1.IsStep)
            {
                if (!Axis1.InPositionCheck(destination[0]))
                {
                    stopReason = $"轴:{Description}到位超时";
                    //MachineMessageScheduler.Instance.Add(new MachineMessage(ExceptionType.NormalError, string.Format("轴{0}到位超时", Description), "Axis", 0));
                    return false;
                }
            }
            if (!Axis2.IsStep)
            {
                if (!Axis2.InPositionCheck(destination[1]))
                {
                    stopReason = $"轴:{Description}到位超时";
                    //MachineMessageScheduler.Instance.Add(new MachineMessage(ExceptionType.NormalError, string.Format("轴{0}到位超时", Description), "Axis", 0));
                    return false;
                }
            }
            _inMove = false;
            //自动模式下记录lastposition
            if (workMode == 1)
            {
                Axis1.LastPosition = destination[0];
                Axis2.LastPosition = destination[1];
            }
            return true;
        }
        public bool IsMovementDone()
        {
            return Axis1.Ready && Axis2.Ready;
        }
        public void ClearErr()
        {
            Axis1.ClearErr();
            Axis2.ClearErr();
        }
        public void SetCard(ControlCard card, short crdNo)
        {
            this._card = card;
            this._crdNo = crdNo;
        }
    }
}
